package cn.lecosa.util;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.commons.lang3.time.FastDateFormat;

import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 日期工具类
 */
public class DateUtil {

    public static final String MILLI_PATTERN = "yyyy-MM-dd HH:mm:ss.SSS";
    public static final String MINUTE_PATTERN = "yyyy-MM-dd HH:mm";
    public static final String SECONDS_PATTERN = "yyyy-MM-dd HH:mm:ss";
    public static final String DATE_PATTERN = "yyyy-MM-dd";
    public static final String DATE_PATTERN1 = "yyyyMMdd";
    public static final String MONTH_PATTERN = "yyyy-MM";
    public static final String YEAR_PATTERN = "yyyy";
    public static final String MINUTE_ONLY_PATTERN = "mm";
    public static final String HOUR_ONLY_PATTERN = "HH";

    private static final int SECONDS_PER_MINUTE = 60;
    private static final int MINUTES_PER_HOUR = 60;
    private static final int HOURS_PER_DAY = 24;
    private static final int SECONDS_PER_DAY = (HOURS_PER_DAY * MINUTES_PER_HOUR * SECONDS_PER_MINUTE);
    /**
     一天的毫秒数
     **/
    private static final long DAY_MILLISECONDS = SECONDS_PER_DAY * 1000L;

    public static long parseDouble2Long(double numberString){
        int wholeDays = (int)Math.floor(numberString);
        int millisecondsInday = (int)((numberString - wholeDays) * DAY_MILLISECONDS + 0.5);
        Calendar calendar = new GregorianCalendar();
        setCalendar(calendar, wholeDays, millisecondsInday, false);
        return calendar.getTimeInMillis();
    }


    /**
     * 转换 Timestamp 格式为 yyyyMMddHHmmssSSS
     * @param timestamp
     * @return
     */
    public static String formatTimeStamp(Timestamp timestamp) {
        if(timestamp == null) {
            return "";
        }
        try {
            FastDateFormat fastDateFormat = FastDateFormat.getInstance("yyyyMMddHHmmssSSS");
            return fastDateFormat.format(timestamp);
        } catch (Exception e) {
            return "";
        }
    }

    /**
     * 转换 Date 格式为 yyyyMMddHHmmss
     * @param date
     * @return
     */
    public static String formatDate(Date date) {
        if(date == null) {
            return "";
        }
        try {
            FastDateFormat fastDateFormat = FastDateFormat.getInstance("yyyyMMddHHmmss");
            return fastDateFormat.format(date);
        } catch (Exception e) {
            return "";
        }
    }

    /**
     * 转换任意格式到 HHmmss
     *
     * @return
     */
    public static String parse2Timestr(String str) {

        str = StringUtils.trimToEmpty(str);



        String[] sfms = {"HH:mm:ss", "HH:mm","HH","HH-mm-ss","HH-mm","HH/mm/ss","HH/mm","HHmmss","HHmm","HH时mm分ss","HH时mm分"};
        String[] hms = {".S", ".SSS"};
        String[] kxs = {"", " "};
        List<String> list = new ArrayList<String>(32);
        for (String kx : kxs) {
                for (String sfm : sfms) {
                    for (String hm : hms) {
                        list.add( kx + sfm + hm);
                    }
                    list.add( kx + sfm);
                }
                list.add( kx);
        }

        try {
            Date date = DateUtils.parseDateStrictly(str, String.join(",", list).split(","));
            return DateFormatUtils.format(date, "HHmmss");
        } catch (ParseException e) {
            try {
                return str;
            } catch (NumberFormatException e1) {
                return str;
            }

        }

    }


    /**
     * 日期格式字符串转换成时间戳
     *
     * @param date_str 字符串日期
     * @param format   如：yyyy-MM-dd HH:mm:ss
     * @return
     */
    public static String dateToStamp(String date_str, String format) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat(format);
            return String.valueOf(sdf.parse(date_str).getTime());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }



    /**
     * 得到系统当前日期及时间，并用指定的方式格式化
     *
     * @param pattern 显示格式
     * @return 当前日期及时间
     */
    public static String getNowDateTime(String pattern) throws ParseException {
        return dateFormat(Calendar.getInstance().getTime(), pattern);
    }


    /**
     * 时间戳转换成Date
     *
     * @param millis
     * @return
     * @throws ParseException
     */
    public static Date parseDate(long millis) throws ParseException {
        return new Date(millis);
    }

    /**
     * 日期字符串转换成Date
     *
     * @param str
     * @param pattern
     * @return
     * @throws ParseException
     */
    public static Date parseDate(String str, String pattern) throws ParseException {
        return DateUtils.parseDate(str, pattern);
    }

    /**
     * 时间戳格式成字符串
     *
     * @param millis
     * @param pattern 如果为空，则为yyyy-MM-dd HH:mm:ss
     * @return
     * @throws ParseException
     */
    public static String dateFormat(long millis, String pattern) throws ParseException {
        if (StringUtils.isBlank(pattern)) {
            pattern = SECONDS_PATTERN;
        }
        return DateFormatUtils.format(millis, pattern);
    }

    /**
     * 时间戳格式成字符串
     *
     * @param millis
     * @param pattern 如果为空，则为yyyy-MM-dd HH:mm:ss
     * @return
     * @throws ParseException
     */
    public static String dateFormat(String millis, String pattern) throws ParseException {
        return dateFormat(Long.valueOf(millis), pattern);
    }

    /**
     * 时间格式化成字符串
     *
     * @param date    Date
     * @param pattern 如果为空，则为yyyy-MM-dd HH:mm:ss
     * @return
     * @throws ParseException
     */
    public static String dateFormat(Date date, String pattern) throws ParseException {
        if (StringUtils.isBlank(pattern)) {
            return dateFormat(date);
        }
        return DateFormatUtils.format(date, pattern);
    }

    /**
     * 日期字符串转换新的格式
     *
     * @param str
     * @param oldpattern
     * @param newpattern
     * @return
     * @throws ParseException
     */
    public static String dateConvertFormat(String str, String oldpattern, String newpattern) {
        String result = str;
        try {
            result = dateFormat(parseDate(str, oldpattern), newpattern);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 时间格式化成字符串  yyyy-MM-dd HH:mm:ss
     *
     * @param date Date
     * @return
     * @throws ParseException
     */
    public static String dateFormat(Date date) throws ParseException {
        return DateFormatUtils.format(date, SECONDS_PATTERN);
    }

    /**
     * 增加年份
     *
     * @param date
     * @param amount
     * @return
     */
    public static Date addYears(final Date date, final int amount) {
        return DateUtils.addYears(date, amount);
    }

    /**
     * 增加月份
     *
     * @param date
     * @param amount
     * @return
     */
    public static Date addMonths(final Date date, final int amount) {
        return DateUtils.addMonths(date, amount);
    }

    /**
     * 增加周
     *
     * @param date
     * @param amount
     * @return
     */
    public static Date addWeeks(final Date date, final int amount) {
        return DateUtils.addWeeks(date, amount);
    }

    /**
     * 增加日期
     *
     * @param date
     * @param amount
     * @return
     */
    public static Date addDays(final Date date, final int amount) {
        return DateUtils.addDays(date, amount);
    }

    /**
     * 增加分钟
     *
     * @param date
     * @param amount
     * @return
     */
    public static Date addMinutes(final Date date, final int amount) {
        return DateUtils.addMinutes(date, amount);
    }

    /**
     * 增加小时
     *
     * @param date
     * @param amount
     * @return
     */
    public static Date addHours(final Date date, final int amount) {
        return DateUtils.addHours(date, amount);
    }

    /**
     * 增加秒
     *
     * @param date
     * @param amount
     * @return
     */
    public static Date addSeconds(final Date date, final int amount) {
        return DateUtils.addSeconds(date, amount);
    }

    /**
     * 增加毫秒
     *
     * @param date
     * @param amount
     * @return
     */
    public static Date addMilliseconds(final Date date, final int amount) {
        return DateUtils.addMilliseconds(date, amount);
    }

    /**
     * 获取当前年
     *
     * @return
     */
    public static int getNowYear() {
        Calendar d = Calendar.getInstance();
        return d.get(Calendar.YEAR);
    }

    /**
     * 获取当前月份
     *
     * @return
     */
    public static int getNowMonth() {
        Calendar d = Calendar.getInstance();
        return d.get(Calendar.MONTH) + 1;
    }

    /**
     * 获取当月天数
     *
     * @return
     */
    public static int getNowMonthDay() {
        Calendar d = Calendar.getInstance();
        return d.getActualMaximum(Calendar.DATE);
    }

    /**
     * 获取日期时间的年份，如2017-02-13，返回2017
     *
     * @param date
     * @return
     */
    public static int getYear(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.get(Calendar.YEAR);
    }

    /**
     * 获取日期时间的月份，如2017年2月13日，返回2
     *
     * @param date
     * @return
     */
    public static int getMonth(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.get(Calendar.MONTH) + 1;
    }

    /**
     * 获取日期时间的第几天（即返回日期的dd），如2017-02-13，返回13
     *
     * @param date
     * @return
     */
    public static int getDate(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.get(Calendar.DATE);
    }

    /**
     * 获取日期时间当月的总天数，如2017-02-13，返回28
     *
     * @param date
     * @return
     */
    public static int getDaysOfMonth(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.getActualMaximum(Calendar.DATE);
    }

    /**
     * 获取日期时间当年的总天数，如2017-02-13，返回2017年的总天数
     *
     * @param date
     * @return
     */
    public static int getDaysOfYear(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.getActualMaximum(Calendar.DAY_OF_YEAR);
    }
    public static String getdpDateStr() {
        String dateFormat = "yyyyMMdd";
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateFormat);

        return "dp=" + simpleDateFormat.format(new Date());
    }

    private static void setCalendar(Calendar calendar, int wholeDays,
                                    int millisecondsInDay, boolean use1904windowing) {
        int startYear = 1900;
        int dayAdjust = -1; // Excel thinks 2/29/1900 is a valid date, which it isn't
        if (use1904windowing) {
            startYear = 1904;
            dayAdjust = 1; // 1904 date windowing uses 1/2/1904 as the first day
        }
        else if (wholeDays < 61) {
            // Date is prior to 3/1/1900, so adjust because Excel thinks 2/29/1900 exists
            // If Excel date == 2/29/1900, will become 3/1/1900 in Java representation
            dayAdjust = 0;
        }
        calendar.set(startYear,0, wholeDays + dayAdjust, 0, 0, 0);
        calendar.set(GregorianCalendar.MILLISECOND, millisecondsInDay);
    }

    /**
     * 转换年月日格式的时间为日期
     * @param str
     * @return
     */
    public static Date parseNyr2Date(String str)  {
        return  getDateStrictly(str, nyrList);
    }
    /**
     * 转换年月日到date
     * @param str
     * @return
     */
    public static Date parseYrn2Date(String str) {
        return  getDateStrictly(str, yrnList);
    }


    private  static List<String> nyrList = new ArrayList<String>();
    private  static List<String> yrnList = new ArrayList<String>();
    static {
        String[] nyrs = {"yy-MM-dd", "yy/MM/dd", "yyMMdd","yy年MM月dd日", "yyyy-MM-dd", "yyyy/MM/dd", "yyyyMMdd","yyyy年MM月dd日"};
        String[] yrns = {"MM-dd-yy", "MM/dd/yy", "MMddyy","MM月dd日yy", "MM-dd-yyyy", "MM/dd/yyyy", "MMddyyyy","MM月dd日yyyy年"};

        String[] sfms = {"HH:mm:ss", "HH:mm","HH","HH-mm-ss","HH-mm","HH/mm/ss","HH/mm","HHmmss","HHmm","HH时mm分ss秒","HH时mm分"};

        String[] hms = {".SSS"};
        String[] kxs = {""," "};

        generateDateParternList(nyrs, sfms, hms, kxs, nyrList);
        generateDateParternList(yrns, sfms, hms, kxs, yrnList);
    }

    private static Date getDateStrictly(String str, List<String> list) {
        try {
            return DateUtils.parseDateStrictly(str, String.join(",", list).split(","));
        } catch (ParseException e) {
        }
        return null;
    }

    private static void generateDateParternList(String[] nyrs, String[] sfms, String[] hms, String[] kxs, List<String> list) {
        for (String kx : kxs) {
            for (String nys : nyrs) {
                for (String sfm : sfms) {
                    for (String hm : hms) {
                        list.add(nys + kx + sfm + hm);
                    }
                    list.add(nys + kx + sfm);
                }
                list.add(nys + kx);
            }
        }
    }
    public static void main(String[] args) throws Exception {
        System.out.println(DateUtil.dateFormat("1522252610000", SECONDS_PATTERN));
        System.out.println(DateUtil.dateToStamp("2018-03-28 23:56:50", SECONDS_PATTERN));
    }

}
